package com.telit.firecommand.util;

import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSON;
import com.telit.common.entity.PageData;
import com.telit.common.exception.ForestBaseException;
import com.telit.common.util.AESUtils;
import com.telit.common.util.RedisUtils;
import com.telit.common.util.WebUtils;
import com.telit.firecommand.config.properties.MaterialProperties;
import com.telit.firecommand.constant.RedisKeyConstant;
import com.telit.firecommand.vo.GoodsStockVO;
import com.telit.firecommand.vo.StoreHouseVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;

import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;


/**
 * 第三方物资储备工具类
 *
 * @author yuezhuang
 * @date 2022-10-28
 */
@Slf4j
public class MaterialUtils {

    private static String API_URL;
    private static String APP_KEY;
    private static String APP_SECRET;
    private static String AES_KEY;
    private static String IV;

    public static final String GET_ACCESS_TOKEN_URI = "/service/ThreeInterface/auth/getAccessToken";
    public static final String GET_STORE_HOUSE_LIST_URI = "/service/ThreeInterface/StoreHouse/getStoreHouseList";
    public static final String GET_GOODS_STOCK_LIST_URI = "/service/ThreeInterface/getGoodsStockList/getGoodsStockList";

    private static final Map<String, String> HEADERS = new HashMap<>();

    /**
     * 初始化配置信息
     *
     * @param materialProperties 配置信息
     */
    public static void init(MaterialProperties materialProperties) {
        API_URL = materialProperties.getApiUrl();
        APP_KEY = materialProperties.getAppKey();
        APP_SECRET = materialProperties.getAppSecret();
        AES_KEY = materialProperties.getAesKey();
        IV = materialProperties.getIv();
    }

    public static void main(String[] args) {
        String accessToken = getAccessToken();
        System.out.println(accessToken);
    }

    /**
     * 获取 access_token
     *
     * @return access_token
     */
    @SuppressWarnings("unchecked")
    private static String getAccessToken() {
        String accessToken = RedisUtils.get(RedisKeyConstant.MATERIAL_ACCESS_TOKEN);
        if (StringUtils.isNotEmpty(accessToken)) {
            return accessToken;
        }

        Map<String, String> requestParams = new HashMap<>();
        requestParams.put("appKey", APP_KEY);
        requestParams.put("appSecret", APP_SECRET);
        Map<String, Object> dataMap = callRequest(GET_ACCESS_TOKEN_URI, requestParams);
        accessToken = MapUtil.getStr(
                Objects.requireNonNull(JSON.parseArray(MapUtil.getStr(dataMap, "values"), Map.class)).get(0),
                "access_token");
        RedisUtils.set(RedisKeyConstant.MATERIAL_ACCESS_TOKEN, accessToken,
                RedisKeyConstant.MATERIAL_ACCESS_TOKEN_EXPIRE_TIME);
        return accessToken;
    }

    /**
     * 查询仓库列表
     *
     * @param page           当前页，分页当前页
     * @param limit          分页条数
     * @param storeHouseName 仓库名称
     *
     * @return List<StoreHouseVO>
     */
    public static List<StoreHouseVO> getStoreHouseList(Integer page, Integer limit, String storeHouseName) {
        Map<String, String> requestParams = new HashMap<>();
        requestParams.put("access_token", getAccessToken());
        requestParams.put("page", page.toString());
        requestParams.put("limit", limit.toString());
        requestParams.put("storeHouseName", storeHouseName);

        Map<String, Object> dataMap = callRequest(GET_STORE_HOUSE_LIST_URI, requestParams);
        return JSON.parseArray(MapUtil.getStr(dataMap, "values"), StoreHouseVO.class);
    }

    /**
     * 查询物资库存列表
     *
     * @param page         当前页，分页当前页
     * @param limit        分页条数
     * @param goodsName    物资名称
     * @param brandName    品牌名称
     * @param modelName    型号名称
     * @param storeHouseID 仓库ID
     *
     * @return List<GoodsStockVO>
     */
    public static PageData<List<GoodsStockVO>> getGoodsStockList(Integer page, Integer limit, String goodsName,
                                                                 String brandName, String modelName,
                                                                 String storeHouseID) {
        Map<String, String> requestParams = new HashMap<>();
        requestParams.put("access_token", getAccessToken());
        requestParams.put("page", page.toString());
        requestParams.put("limit", limit.toString());
        requestParams.put("goodsName", goodsName);
        requestParams.put("brandName", brandName);
        requestParams.put("modelName", modelName);
        requestParams.put("storeHouseID", storeHouseID);

        Map<String, Object> dataMap = callRequest(GET_GOODS_STOCK_LIST_URI, requestParams);
        List<GoodsStockVO> values = JSON.parseArray(MapUtil.getStr(dataMap, "values"), GoodsStockVO.class);
        int total = MapUtil.getInt(dataMap, "count");

        return PageData.<List<GoodsStockVO>>builder()
                .count(total)
                .current(page)
                .size(limit)
                .datas(values)
                .build();
    }

    /**
     * http请求
     *
     * @param url           请求地址
     * @param requestParams 请求参数
     *
     * @return http请求结果
     */
    @SuppressWarnings("unchecked")
    public static Map<String, Object> callRequest(String url, Map<String, String> requestParams) {
        try {
            log.info("森林防火物资储备系统，接口地址：{}， 请求参数：{}", API_URL + url, JSON.toJSONString(requestParams));
            String result = WebUtils.doPostWithRequestParameters(API_URL + url, requestParams, HEADERS);
            log.info("森林防火物资储备系统，返回结果：{}", result);

            Map<String, Object> resultMap = JSON.parseObject(result, Map.class);
            Validate.isTrue(MapUtil.getInt(resultMap, "flag") == 0);
            String data = MapUtil.getStr(resultMap, "data");
            byte[] bytes = AESUtils.decrypt(Base64.decodeBase64(data.getBytes(StandardCharsets.UTF_8)),
                    AES_KEY.getBytes(StandardCharsets.UTF_8), IV.getBytes(StandardCharsets.UTF_8),
                    AESUtils.ALGORITHM_AES_CBC_PKCS5PADDING);
            String decryptData = new String(bytes, StandardCharsets.UTF_8);
            log.info("森林防火物资储备系统，返回结果解密：{}", decryptData);

            return JSON.parseObject(decryptData, Map.class);
        } catch (Exception e) {
            log.error("森林防火物资储备系统，调用失败：{}", e.getMessage());

            throw new ForestBaseException("森林防火物资储备系统，调用失败：" + e.getMessage());
        }
    }

}
